﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using X3DXNA.services;
using X3DXNA.interfaces;
using X3DXNA.core.Boundings;
using X3DXNA.X3DSchema;
using X3DXNA.utils;
using X3DXNA.core.CustomNodes;

namespace X3DXNA.basicModels
{
    class basicBox : IGeometry
    {
        VertexPositionNormalTexture[] cubeVertices;
        VertexBuffer vertexBuffer;
        myBasicEffect basicEffect;
        MyBoundingBox boundingBox;
        Vector3 size;
        Matrix world = Matrix.Identity;
        Game game;
        public String DEF { get; set; }
        public Matrix World { get { return world; } set { world = value; } }
        public Matrix getBasicTransformation { get { return Matrix.Identity; } }

        public void applyWorldTransformation(Matrix transformation)
        {
            world *= transformation;
        }

        public basicBox(Game game,String DEF, Vector3 size, Matrix transformation, bool isDynamic)
        {
            this.DEF = DEF;
            this.game = game;
            this.size = size;
            
            this.basicEffect = (myBasicEffect)game.Services.GetService(typeof(myBasicEffect));

            Vector3 topLeftFront = new Vector3(-0.5f, 0.5f, 0.5f) * size;
            Vector3 bottomLeftFront = new Vector3(-0.5f, -0.5f, 0.5f) * size;
            Vector3 topRightFront = new Vector3(0.5f, 0.5f, 0.5f) * size;
            Vector3 bottomRightFront = new Vector3(0.5f, -0.5f, 0.5f) * size;
            Vector3 topLeftBack = new Vector3(-0.5f, 0.5f, -0.5f) * size;
            Vector3 topRightBack = new Vector3(0.5f, 0.5f, -0.5f) * size;
            Vector3 bottomLeftBack = new Vector3(-0.5f, -0.5f, -0.5f) * size;
            Vector3 bottomRightBack = new Vector3(0.5f, -0.5f, -0.5f) * size;

            //Se questa shape sarà statica, effettueremo la trasformazione dei suoi vertici, per risparmiare futuri calcoli.
            if (!isDynamic)
            {
                topLeftFront = Vector3.Transform(topLeftFront, transformation);
                bottomLeftFront = Vector3.Transform(bottomLeftFront, transformation);
                topRightFront = Vector3.Transform(topRightFront, transformation);
                bottomRightFront = Vector3.Transform(bottomRightFront, transformation);
                topLeftBack = Vector3.Transform(topLeftBack, transformation);
                topRightBack = Vector3.Transform(topRightBack, transformation);
                bottomLeftBack = Vector3.Transform(bottomLeftBack, transformation);
                bottomRightBack = Vector3.Transform(bottomRightBack, transformation);
            }

            boundingBox = new MyBoundingBox(BoundingBox.CreateFromPoints(new Vector3[] { topLeftBack, bottomLeftFront, 
                                                                                         topRightFront, bottomRightFront,
                                                                                         topLeftBack, topRightBack,
                                                                                         bottomLeftBack, bottomRightBack}));

            Vector2 textureTopLeft = new Vector2(0.5f, 0.0f);
            Vector2 textureTopRight = new Vector2(0.0f, 0.0f);
            Vector2 textureBottomLeft = new Vector2(0.5f, 0.5f);
            Vector2 textureBottomRight = new Vector2(0.0f, 0.5f);

            Vector3 frontNormal = new Vector3(0.0f, 0.0f, 1.0f);
            Vector3 backNormal = new Vector3(0.0f, 0.0f, -1.0f);
            Vector3 topNormal = new Vector3(0.0f, 1.0f, 0.0f);
            Vector3 bottomNormal = new Vector3(0.0f, -1.0f, 0.0f);
            Vector3 leftNormal = new Vector3(-1.0f, 0.0f, 0.0f);
            Vector3 rightNormal = new Vector3(1.0f, 0.0f, 0.0f);

            cubeVertices = new VertexPositionNormalTexture[36];

            // Front face.
            cubeVertices[0] = new VertexPositionNormalTexture(
                topLeftFront, frontNormal, textureTopLeft);
            cubeVertices[1] = new VertexPositionNormalTexture(
                bottomLeftFront, frontNormal, textureBottomLeft);
            cubeVertices[2] = new VertexPositionNormalTexture(
                topRightFront, frontNormal, textureTopRight);
            cubeVertices[3] = new VertexPositionNormalTexture(
                bottomLeftFront, frontNormal, textureBottomLeft);
            cubeVertices[4] = new VertexPositionNormalTexture(
                bottomRightFront, frontNormal, textureBottomRight);
            cubeVertices[5] = new VertexPositionNormalTexture(
                topRightFront, frontNormal, textureTopRight);

            // Back face.
            cubeVertices[6] = new VertexPositionNormalTexture(
                topLeftBack, backNormal, textureTopRight);
            cubeVertices[7] = new VertexPositionNormalTexture(
                topRightBack, backNormal, textureTopLeft);
            cubeVertices[8] = new VertexPositionNormalTexture(
                bottomLeftBack, backNormal, textureBottomRight);
            cubeVertices[9] = new VertexPositionNormalTexture(
                bottomLeftBack, backNormal, textureBottomRight);
            cubeVertices[10] = new VertexPositionNormalTexture(
                topRightBack, backNormal, textureTopLeft);
            cubeVertices[11] = new VertexPositionNormalTexture(
                bottomRightBack, backNormal, textureBottomLeft);

            // Top face.
            cubeVertices[12] = new VertexPositionNormalTexture(
                topLeftFront, topNormal, textureBottomLeft);
            cubeVertices[13] = new VertexPositionNormalTexture(
                topRightBack, topNormal, textureTopRight);
            cubeVertices[14] = new VertexPositionNormalTexture(
                topLeftBack, topNormal, textureTopLeft);
            cubeVertices[15] = new VertexPositionNormalTexture(
                topLeftFront, topNormal, textureBottomLeft);
            cubeVertices[16] = new VertexPositionNormalTexture(
                topRightFront, topNormal, textureBottomRight);
            cubeVertices[17] = new VertexPositionNormalTexture(
                topRightBack, topNormal, textureTopRight);

            // Bottom face. 
            cubeVertices[18] = new VertexPositionNormalTexture(
                bottomLeftFront, bottomNormal, textureTopLeft);
            cubeVertices[19] = new VertexPositionNormalTexture(
                bottomLeftBack, bottomNormal, textureBottomLeft);
            cubeVertices[20] = new VertexPositionNormalTexture(
                bottomRightBack, bottomNormal, textureBottomRight);
            cubeVertices[21] = new VertexPositionNormalTexture(
                bottomLeftFront, bottomNormal, textureTopLeft);
            cubeVertices[22] = new VertexPositionNormalTexture(
                bottomRightBack, bottomNormal, textureBottomRight);
            cubeVertices[23] = new VertexPositionNormalTexture(
                bottomRightFront, bottomNormal, textureTopRight);

            // Left face.
            cubeVertices[24] = new VertexPositionNormalTexture(
                topLeftFront, leftNormal, textureTopRight);
            cubeVertices[25] = new VertexPositionNormalTexture(
                bottomLeftBack, leftNormal, textureBottomLeft);
            cubeVertices[26] = new VertexPositionNormalTexture(
                bottomLeftFront, leftNormal, textureBottomRight);
            cubeVertices[27] = new VertexPositionNormalTexture(
                topLeftBack, leftNormal, textureTopLeft);
            cubeVertices[28] = new VertexPositionNormalTexture(
                bottomLeftBack, leftNormal, textureBottomLeft);
            cubeVertices[29] = new VertexPositionNormalTexture(
                topLeftFront, leftNormal, textureTopRight);

            // Right face. 
            cubeVertices[30] = new VertexPositionNormalTexture(
                topRightFront, rightNormal,textureTopLeft);
            cubeVertices[31] = new VertexPositionNormalTexture(
                bottomRightFront, rightNormal, textureBottomLeft);
            cubeVertices[32] = new VertexPositionNormalTexture(
                bottomRightBack, rightNormal, textureBottomRight);
            cubeVertices[33] = new VertexPositionNormalTexture(
                topRightBack, rightNormal, textureTopRight);
            cubeVertices[34] = new VertexPositionNormalTexture(
                topRightFront, rightNormal, textureTopLeft);
            cubeVertices[35] = new VertexPositionNormalTexture(
                bottomRightBack, rightNormal, textureBottomRight);


            initializeVertexBuffer();
        }

        public void initializeVertexBuffer()
        {
            vertexBuffer = new VertexBuffer(
                game.GraphicsDevice,
                VertexPositionNormalTexture.VertexDeclaration,
                36,
                BufferUsage.None
            );

            vertexBuffer.SetData<VertexPositionNormalTexture>(cubeVertices);
        }

        public void draw()
        {
            game.GraphicsDevice.SetVertexBuffer(vertexBuffer);

            foreach (EffectPass pass in basicEffect.getBasicEffect.CurrentTechnique.Passes)
            {
                pass.Apply();

                game.GraphicsDevice.DrawPrimitives(
                    PrimitiveType.TriangleList,
                    0,
                    12
                );

            }
        }

        public IBounding retrieveBounding()
        {
            return boundingBox;
        }

        public static basicBox getNewBasicBox(Game game, Box box, Matrix transformation, bool isDynamic)
        {
            String DEF = "Standard Box";
            Vector3 size = new Vector3(2, 2, 2);
            if (box.DEF != null)
                DEF = box.DEF;
            if (box.size != null)
                size = utility.stringToVector3(box.size);

            return new basicBox(game, box.DEF, size, transformation, isDynamic);
        }

        public Vector3[] getTriangleVertices()
        {
            return null;
        }
    }
}
